package com.hp.nacos.config;

import com.alibaba.fastjson2.JSON;
import com.dtp.core.spring.EnableDynamicTp;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.retry.RetryCallback;
import org.springframework.retry.RetryContext;
import org.springframework.retry.RetryListener;
import org.springframework.retry.annotation.EnableRetry;
import org.springframework.retry.backoff.FixedBackOffPolicy;
import org.springframework.retry.policy.SimpleRetryPolicy;
import org.springframework.retry.support.RetryTemplate;

import java.util.UUID;

@SpringBootApplication
@EnableRetry
@EnableDynamicTp
public class SpringBootNacosConfigApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringBootNacosConfigApplication.class, args);
    }

    @Bean
    public RetryListener retryListener1() {
        return new RetryListener() {
            @Override
            public <T, E extends Throwable> boolean open(RetryContext retryContext, RetryCallback<T, E> retryCallback) {
                System.out.println("open context1 = " + retryContext + ", callback = " + retryCallback);
                // 返回true继续执行后续调用
                return true;
            }

            @Override
            public <T, E extends Throwable> void close(RetryContext retryContext, RetryCallback<T, E> retryCallback, Throwable throwable) {
                System.out.println("close context1 = " + retryContext + ", callback = " + retryCallback);

            }

            @Override
            public <T, E extends Throwable> void onError(RetryContext retryContext, RetryCallback<T, E> retryCallback, Throwable throwable) {
                System.out.println("onError context1 = " + retryContext + ", callback = " + retryCallback);

            }
        };
    }


    @Bean
    public RetryListener retryListener2() {
        return new RetryListener() {
            @Override
            public <T, E extends Throwable> boolean open(RetryContext retryContext, RetryCallback<T, E> retryCallback) {
                //final String[] strings = retryContext.attributeNames();
                //final Iterator<String> iterator = Arrays.stream(strings).iterator();
                //while (iterator.hasNext()) {
                //    final String next = iterator.next();
                //    System.out.println(next);
                //    System.out.println(retryContext.getAttribute(next));
                //}
                final UUID uuid = UUID.randomUUID();
                System.out.println(uuid);
                retryContext.setAttribute("request", uuid);
                System.out.println("open context2 = " + JSON.toJSONString(retryContext) + ", callback = " + JSON.toJSONString(retryCallback));
                // 返回true继续执行后续调用
                return true;
            }

            @Override
            public <T, E extends Throwable> void close(RetryContext retryContext, RetryCallback<T, E> retryCallback, Throwable throwable) {
                System.out.println(retryContext.getAttribute("request"));
                System.out.println("close context2 = " + JSON.toJSONString(retryContext) + ", callback = " + JSON.toJSONString(retryCallback));

            }

            @Override
            public <T, E extends Throwable> void onError(RetryContext retryContext, RetryCallback<T, E> retryCallback, Throwable throwable) {
                System.out.println(retryContext.getAttribute("request"));
                System.out.println("onError context2 = " + JSON.toJSONString(retryContext) + ", callback = " + JSON.toJSONString(retryCallback));

            }
        };
    }


    /**
     * 重试模板
     *
     * @return {@link RetryTemplate}
     */
    @Bean
    public RetryTemplate retryTemplate() {
        SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy();
        // 启用 4次
        retryPolicy.setMaxAttempts(4);

        FixedBackOffPolicy backOffPolicy = new FixedBackOffPolicy();
        // 3秒
        backOffPolicy.setBackOffPeriod(3000);
        RetryTemplate template = new RetryTemplate();
        template.setRetryPolicy(retryPolicy);
        template.setBackOffPolicy(backOffPolicy);
        template.registerListener(new RetryListener() {
            @Override
            public <T, E extends Throwable> boolean open(RetryContext retryContext, RetryCallback<T, E> retryCallback) {
                //final String[] strings = retryContext.attributeNames();
                //final Iterator<String> iterator = Arrays.stream(strings).iterator();
                //while (iterator.hasNext()) {
                //    final String next = iterator.next();
                //    System.out.println(next);
                //    System.out.println(retryContext.getAttribute(next));
                //}
                final UUID uuid = UUID.randomUUID();
                System.out.println(uuid);
                retryContext.setAttribute("request", uuid);
                System.out.println("open context2 = " + JSON.toJSONString(retryContext) + ", callback = " + JSON.toJSONString(retryCallback));
                // 返回true继续执行后续调用
                return true;
            }

            @Override
            public <T, E extends Throwable> void close(RetryContext retryContext, RetryCallback<T, E> retryCallback, Throwable throwable) {
                System.out.println(retryContext.getAttribute("request"));
                System.out.println("close context2 = " + JSON.toJSONString(retryContext) + ", callback = " + JSON.toJSONString(retryCallback));

            }

            @Override
            public <T, E extends Throwable> void onError(RetryContext retryContext, RetryCallback<T, E> retryCallback, Throwable throwable) {
                System.out.println(retryContext.getAttribute("request"));
                System.out.println("onError context2 = " + JSON.toJSONString(retryContext) + ", callback = " + JSON.toJSONString(retryCallback));

            }
        });
        return template;
    }
}
